/**
 * @file gjson_value.c
 * @brief the value of key-value
 * @author JakeYang <add358@gmail.com>
 * @version 0.1
 * @date 2016-03-01
 */

#include "gjson_value.h"
#include "gjson_object.h"
#include "gjson_array.h"

GJsonValue *g_json_value_parse(GJsonData *d)
{
    GJsonValue *v = NULL;
    gpointer val = NULL;
    GJsonType type = GJSON_NOTHING;

    if (_equal_char(d, '\"')) {
        /* string */
        type = GJSON_STRING;
        val = g_json_data_get_str(d);
    } else if (_equal_char(d, '{')) {
        /* object */
        type = GJSON_OBJECT;
        val = g_json_object_parse(d);
    } else if (_equal_str(d, "null", 4)) {
        /* null */
        _forward(d, 4);
    } else if (_equal_str(d, "false",5)) {
        /* boolean: false*/
        type = GJSON_BOOLEAN;
        val = GINT_TO_POINTER(FALSE);
        _forward(d, 5);
    } else if (_equal_str(d, "true", 4)) {
        /* boolean true */
        type = GJSON_BOOLEAN;
        val = GINT_TO_POINTER(TRUE);
        _forward(d, 4);
    } else if (_equal_char(d, '-')
               || ('\0' <= g_json_data_char(d) && '9' >= g_json_data_char(d))) {
        /* number */
        type = GJSON_NUMBER;
        val = g_json_data_get_number(d);
    } else if (_equal_char(d, '[')) {
        /* arrary */
        type = GJSON_ARRAY;
        val = g_json_array_parse(d);
    } else {
        return NULL;
    }

    if (NULL == val && GJSON_NOTHING != type && GJSON_BOOLEAN != type) {
        return NULL;
    }

    v = g_malloc0(sizeof(GJsonValue));

    v->type = type;
    v->value = val;

    return v;
}

void g_json_value_free(gpointer value)
{
    GJsonValue *v = (GJsonValue *)value;
    if (GJSON_STRING == v->type) {
        g_free(v->value);
    } else if( GJSON_OBJECT == v->type ) {
        g_json_destroy(v->value);
    } else if ( GJSON_NUMBER == v->type) {
        g_free(v->value);
    } else if ( GJSON_ARRAY == v->type) {
        g_json_array_free(v->value);
    }
    g_free(v);
}

void g_json_value_print(const GJsonValue *v, GJsonText *t)
{
    switch (v->type) {
    case GJSON_NOTHING:
        g_string_append(t->str, "null");
        break;
    case GJSON_STRING:
        g_string_append_printf(t->str,"\"%s\"", (gchar *)(v->value));
        break;
    case GJSON_OBJECT:
        g_json_object_print(v->value, t);
        break;
    case GJSON_ARRAY: {
        gchar *tmp = g_json_array_print(v->value);
        g_string_append(t->str, tmp);
        g_free(tmp);
    };
        break;
    case GJSON_BOOLEAN:
        if (GPOINTER_TO_INT(v->value)) {
            g_string_append(t->str, "true");
        } else {
            g_string_append(t->str, "false");
        }
        break;
    case GJSON_NUMBER:
        g_string_append(t->str, v->value);
    default:
        break;
    }
    g_string_append(t->str, ",");
}
